home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1993 July / InfoMagic USENET CD-ROM July 1993.ISO / sources / unix / volume25 / hexpert < prev    next >
Encoding:
Text File  |  1992-01-10  |  23.7 KB  |  1,191 lines

  1. Newsgroups: comp.sources.unix
  2. From: dom@dsbc.icl.co.uk (Dominic Alston)
  3. Subject: v25i095: hexpert - a binary file editor for SysV
  4. Sender: sources-moderator@pa.dec.com
  5. Approved: vixie@pa.dec.com
  6.  
  7. Submitted-By: dom@dsbc.icl.co.uk (Dominic Alston)
  8. Posting-Number: Volume 25, Issue 95
  9. Archive-Name: hexpert
  10.  
  11. [ I don't have a System V machine so I had to ask a friend to evaluate
  12.   this submission.  Here are his comments:
  13.  
  14. [[
  15.   Not a bad binary file editor.  A manual page isn't really necessary
  16.   since the program is simple and self documenting, though a manual
  17.   page would have been nice.  I compiled and ran this on my Sun
  18.   workstation (using the System V flavored cc, /usr/5bin/cc) and on
  19.   my Compaq 386 running ISC Unix 3.2.  On the Sun everything works as
  20.   expected as long as the screen (window) width was 80 columns.  On ISC
  21.   Unix I had to redefine "ENTER" to be a carriage return instead of a
  22.   newline; otherwise everyting worked fine.  The program calls itself
  23.   "hexpert" but the makefile creates a file called "hex" which might
  24.   conflict with some systems that have the archaic "hex" and "unhex"
  25.   programs.
  26.                             Ken Keirnan
  27.                             Pacific Bell
  28. ]]
  29.  
  30.                                     --vix ]
  31.  
  32. The following is a hex editor for UNIX System V written by myself
  33. a few years back. Enjoy..
  34.  
  35.     dom@dsbc.icl.co.uk (Dominic Alston)
  36.  
  37. #! /bin/sh
  38. # This is a shell archive, meaning:
  39. # 1. Remove everything above the #! /bin/sh line.
  40. # 2. Save the resulting text in a file.
  41. # 3. Execute the file with /bin/sh (not csh) to create the files:
  42. #    Makefile
  43. #    hex.c
  44. # This archive created: Mon Dec 23 20:13:52 1991
  45. export PATH; PATH=/bin:$PATH
  46. if test -f 'Makefile'
  47. then
  48.     echo shar: will not over-write existing file "'Makefile'"
  49. else
  50. cat << \SHAR_EOF > 'Makefile'
  51. hex:    hex.c
  52.     $(CC) hex.c $(CFLAGS) -lcurses -o hex
  53. SHAR_EOF
  54. fi # end of overwriting check
  55. if test -f 'hex.c'
  56. then
  57.     echo shar: will not over-write existing file "'hex.c'"
  58. else
  59. cat << \SHAR_EOF > 'hex.c'
  60. /*----------------------------------------------------------------------------*/
  61. /* Program: hex.c                                  */
  62. /* Date:    27-nov-1988                                  */
  63. /* Desc:    Hex editor source                              */
  64. /* Author:  Dominic Alston                              */
  65. /* Version: 2.4                                      */
  66. /* Revision history:                                   */
  67. /*    25-jan-1989  dom: Added terminal independant code                   */
  68. /*      30-jan-1989  dom: Redesigned screen, added features                   */
  69. /*    03-feb-1989  dom: Modified code.                      */
  70. /*    04-feb-1989  dom: Added own mmi routines                              */
  71. /*      05-feb-1989  dom: Version 2 Increment 0 release finished.             */
  72. /*      06-feb-1989  dom: Fixed goto out of band chars being accepted         */
  73. /*      20-feb-1989  dom: Added version print and readonly feature            */
  74. /*      23-feb-1989  dom: Added screen refresh.                               */
  75. /*----------------------------------------------------------------------------*/
  76.  
  77. #include <sys/types.h>
  78. #include <curses.h>
  79. #include <fcntl.h>
  80. #include <ctype.h>
  81. #include <errno.h>
  82. #include <signal.h>
  83. #include <sys/stat.h>
  84.  
  85. #define VERSION_STAMP "2.4"
  86. #define PAGESIZE 1280
  87. #define BUFSIZE 256
  88. #define READING    0
  89. #define WRITING    1
  90. #define GOTO 2
  91. #define DBUFF_SIZE 32
  92. #define FBUFF_SIZE 16
  93. #define X_PRODUCT 30
  94. #define Y_PRODUCT 0
  95. #define X_MENU1    0
  96. #define Y_MENU1    2
  97. #define X_MENU2    0
  98. #define Y_MENU2    3
  99. #define X_STATUS 0
  100. #define Y_STATUS 5
  101. #define X_FORMAT 76
  102. #define X_POSITION 19
  103. #define X_PROMPT 0
  104. #define Y_PROMPT 6
  105. #define X_INPUT 9
  106. #define X_FIND 9
  107. #define Y_FIND 6
  108. #define X_HEX 0
  109. #define Y_HEX 7
  110. #define X_CHAR 52
  111. #define Y_CHAR 7
  112. #define X_EXIT 0
  113. #define Y_EXIT 23
  114. #define X_VERB 36
  115. #define Y_VERB 5
  116. #define CTRL(c) ((c) & 037)
  117. #define _KEY_EXIT 'q'
  118. #define ENTER '\n'
  119. #define KEY_ESC    '\033'
  120. #define KEY_TAB    '\t'    
  121.  
  122. char *pos_get();
  123. int ctrlc_ast();
  124. static int ch;                /* buffer for single character read           */
  125. static char page[PAGESIZE];    /* buffer for screen display              */
  126. static char *hptr;        /* pointer to page for hex display          */
  127. static char *cptr;        /* pointer to page for character display      */
  128. static char buf[BUFSIZE];    /* buffer for input i/o                  */
  129. static char *bptr;        /* pointer to buf                  */
  130. static char pos[9];        /* buffer for character format of position    */
  131. static char find_buff[FBUFF_SIZE]; /* buffer holding the string for searching */
  132. static int find_length;         /* size of string searched for                */
  133. static char disp_buff[DBUFF_SIZE]; /* buffer holding the search string during */
  134. static int disp_length;
  135. static char hexchars[] = "0123456789ABCDEF";
  136. static char head1[] = "                      Hexpert [v2.4 (c)1988 Dominic Alston]                     ";
  137. static char r_head2[] = 
  138.     "Options: <Up-arrow>  =Page-up    <g>=Goto-position  <c> =Char-find  <q>=Exit   "; /* apm 27/1/85*/
  139. static char r_head3[] = 
  140.     "         <Down-arrow>=Page-down  <h>=Hex-find       <^l>=Refresh              ";
  141. static char head2[] = 
  142.     "Options: <Up-arrow>  =Page-up    <g>=Goto-position  <c>=Char-find  <q> =Exit"; /* apm 27/1/85*/
  143. static char head3[] = 
  144.     "         <Down-arrow>=Page-down  <e>=Edit-buffer    <h>=Hex-find   <^l>=Refresh";
  145. static char head4[] = 
  146.     "Status-  Position: 00000000   Mode: View   File: ";
  147. static char head5[] = 
  148.     "Options: <Enter>=Write-buffer  <Tab>=Toggle hex/char edit                      "; /* apm 27/1/85 */
  149. static char head6[] = 
  150.     "         <Esc>  =Restore buffer & goto view mode                               ";
  151. static char head7[] =
  152.     "Options: <Enter>=Do-search       <Left-arrow>= Move-left                       "; /* apm 27/1/85 */
  153. static char head8[] =
  154.     "         <Esc>  =Goto view mode  <Right-arrow>=Move-right                      ";
  155. static char edit1[] =
  156.     "Options: <Enter>=Goto-position   <Left-arrow>=Move-left                        ";
  157. static char edit2[] =
  158.     "         <Esc>  =Goto view mode  <Right-mode>=Move-right                       ";
  159. static char msg1[] = "pattern not found!";
  160. static char usage_bnr[]=
  161.     "Usage: hex [-vr] 'file'";
  162. static char version_bnr[]=
  163.     "HEXPERT V%s, Dominic Alston..\n";
  164. static char error1[] = "internal error - hex unpaired!";
  165. static int x,y;        /* screen co-ordinates                         */
  166. static int input;    /* file descriptor for input file              */
  167. static int mode;    /* current mode of use                      */
  168. static int readonly;    /* true if input file is read only              */
  169. static int save_flags;    /* dump of terminal info while in RAW mode           */
  170. static int bytes_written;
  171. static int bytes_read;
  172. static char hex_find;    /* true if find mode is currently hex              */
  173. static long position;    /* displacement of current buffer in input file          */
  174. static long lastbyte;   /* displacement of end of file     (Mod 256)            */
  175. static struct stat filedata; /* statistics of the input file,gives file size  */
  176. static int bool_hexfind=FALSE;
  177. extern char *optarg;
  178.  
  179. main(argc,argv)
  180. int argc;
  181. char *argv[];
  182. {
  183.     int c;
  184.     char filenm[80];
  185.  
  186.     while ((c=getopt(argc,argv,"vr:"))!=EOF)
  187.         switch(c)
  188.         {
  189.             case 'v':
  190.                 fprintf(stderr,version_bnr,
  191.                               VERSION_STAMP);
  192.                 exit(-1);
  193.             case 'r':
  194.                 readonly=TRUE;
  195.                 strcpy(filenm,optarg);
  196.                 break;    
  197.             default:
  198.                 fprintf(stderr,"%s\n",usage_bnr);
  199.                 exit(-1);
  200.         }
  201.     if (argc==1)
  202.     {
  203.         fprintf(stderr,"%s\n",usage_bnr);
  204.         exit(-1);
  205.     }
  206.     else
  207.         initialise(filenm[0]==0?argv[1]:filenm);
  208.     toplevel();
  209.     closedown();
  210. }
  211.  
  212. static initialise(filename)
  213. char *filename;
  214. {
  215.     register int i,j; 
  216.     char *ptr;
  217.  
  218.     /* Open file for read & write, if this fails                          */
  219.     /* open file for reading, if fail exit.                              */
  220.     if ((input=open(filename,O_RDWR))==-1) 
  221.         if ((input=open(filename,O_RDONLY))==-1)
  222.         {
  223.             perror(filename);
  224.             exit(-1);
  225.         }
  226.         else
  227.             readonly=TRUE;
  228.     init_term();        /* init curses terminfo                  */
  229.     signal(SIGINT,ctrlc_ast);   /* signal handler for contol c           */
  230.     /* Read the file statistics to find  the                              */
  231.     /* file size and put it in 'lastbyte',                                */
  232.     /* after adjusting to a multiple of 256                               */
  233.     if ((fstat(input,&filedata))==0)
  234.         lastbyte=(filedata.st_size-1) & 0x7fffff00;
  235.     else
  236.         lastbyte = 0;
  237.     /* Clear the display buffer.                               */
  238.     hptr=page;
  239.     for (i=0; i<PAGESIZE; i++) 
  240.         *hptr++=' ';
  241.     attron(A_REVERSE);
  242.     addstr(head1);
  243.     attroff(A_REVERSE);
  244.     toplev_headings();
  245.     mvaddstr(Y_STATUS, X_STATUS,head4);
  246.     /* Display the input file name.                                  */
  247.     i=strlen(filename);
  248.     ptr=filename;
  249.     if (i>33) 
  250.         i=33;
  251.     for (j=0; j<i; j++)
  252.         addch(*ptr++);
  253.     /* Read and display the first 256 bytes                              */
  254.     if (readonly)
  255.     {
  256.         attron(A_BOLD);
  257.         mvaddstr(Y_STATUS,72,"Readonly");
  258.         attroff(A_BOLD);
  259.     }
  260.     refresh();
  261.     position = 0;
  262.     lseek(input,position,0);
  263.     display();
  264.     mode = READING;
  265.     hex_find = FALSE;
  266.     find_length = 0;
  267.     put_prompt();
  268.     refresh();
  269. }
  270.  
  271. static display()
  272. {
  273.     int num;
  274.     register int i;
  275.     int j;
  276.     int jlimit;
  277.     char *pptr;
  278.  
  279.     hptr = page;
  280.     cptr = (hptr + 52);
  281.     bptr = buf;
  282.     pos_print();
  283.     move(Y_HEX, X_HEX);
  284.     if (((num=read(input,buf,BUFSIZE))!=EOF) && (num!=0)) 
  285.     {
  286.         if (num<BUFSIZE) 
  287.         {
  288.             for (i=0; i<PAGESIZE; i++) 
  289.                 *hptr++ = ' ';
  290.             hptr=page;
  291.         }
  292.         for (i=0; i<num; i+=16) 
  293.         {
  294.             jlimit=((num-i)>=16)?16:num-i;
  295.             for (j=0; j<jlimit; j++) 
  296.             {
  297.                 *hptr++=hexchars[(*bptr>>4) & 0xf];
  298.                 *hptr++=hexchars[*bptr & 0xf];
  299.                 *hptr++=' ';
  300.                 *cptr++=((*bptr)>0x1f &&
  301.                      (*bptr)<0x7f?*bptr:'.');
  302.                 bptr++;
  303.             }
  304.             *((cptr-jlimit)+80)='\n';
  305.             hptr+=32;
  306.             cptr=(hptr+52);
  307.         }
  308.     }
  309.     else
  310.         for(i=0; i<PAGESIZE; i++) 
  311.             *hptr++=' ';
  312.     bytes_read=num;
  313.     move(Y_HEX,X_HEX);
  314.     hptr=page;
  315.     for (i=0; i<PAGESIZE; i++)
  316.         addch(*hptr++);
  317.     bytes_written=i; 
  318.     if (bytes_written!=PAGESIZE) 
  319.         closedown();
  320.     put_prompt();
  321.     refresh();
  322. }
  323.  
  324. static closedown()
  325. {
  326.     reset_term();
  327.     exit(0);
  328. }
  329.  
  330. static toplevel()
  331. {
  332.     int num_read;
  333.  
  334.     while ((ch=getch())!=_KEY_EXIT)
  335.     {
  336.         clrtoeol();
  337.         refresh();
  338.         switch(ch) 
  339.         {
  340.             case CTRL('l'):
  341.                 clearok(curscr,TRUE);
  342.                 doupdate();
  343.                 break;
  344.             case KEY_HOME:
  345.                 if (position!=0)
  346.                 {
  347.                     position=0;
  348.                     lseek(input,position,0);
  349.                     display();
  350.                 }
  351.                 else
  352.                     beep();
  353.                 break;
  354.             case KEY_DOWN:    
  355.                 if (position != lastbyte) 
  356.                 {
  357.                     if ((position += 256) > lastbyte)
  358.                         position = lastbyte;
  359.                     lseek(input,position,0);
  360.                     display();
  361.                 }
  362.                 else
  363.                     beep();
  364.                 break;
  365.             case KEY_UP:
  366.                 if (position != 0)
  367.                 {
  368.                     position -= 256;
  369.                     if (position < 0)
  370.                         position = 0;
  371.                     lseek(input,position,0);
  372.                     display();
  373.                 }
  374.                 else
  375.                     beep();
  376.                 break;
  377.             case 'g':
  378.             case 'G':
  379.                 mode=GOTO;
  380.                 if (get_position())
  381.                 {
  382.                     lseek(input,position,0);
  383.                     display();
  384.                 }
  385.                 else
  386.                     pos_print();    
  387.                 toplev_headings();
  388.                 mode=READING;
  389.                 break;
  390.             case 'e':
  391.             case 'E':
  392.                 if (readonly) 
  393.                 {
  394.                     beep();
  395.                     move(6,9);
  396.                     refresh();
  397.                 }
  398.                 else
  399.                     editbuffer();
  400.                 break;
  401.             case 'c':
  402.             case 'C':
  403.             case 'h':
  404.             case 'H':
  405.                 if ((ch=='c') || (ch=='C'))
  406.                     hex_find=FALSE;
  407.                 else
  408.                     hex_find=TRUE;
  409.                 if (get_string()==1)
  410.                     find_string();
  411.                 toplev_headings();
  412.                 break;
  413.             default:    
  414.                 beep();
  415.                 break;
  416.         }
  417.     }
  418. }
  419.  
  420. static get_position()
  421. {
  422.     char num[9];
  423.     char *ptr1,*ptr2;
  424.     int status;
  425.     long posit;
  426.     register int i;
  427.  
  428.     edit_headings();
  429.     posit=0;
  430.     ptr1=num;
  431.     ptr2=pos;
  432.     for (i=0; i<9; i++) 
  433.         (*(ptr1++))=(*(ptr2++));
  434.     move(Y_STATUS,10);
  435.     disp_length=7;
  436.     if ((status=get_str(stdscr,Y_STATUS,X_POSITION,num,'0',8))==-1)
  437.         return(FALSE);
  438.     for (i=0; i<8; i++) 
  439.     {
  440.         posit=(posit<<4)+(num[i] & 0xf);
  441.         if (num[i]>'9') 
  442.             posit+=9;
  443.     }
  444.     if (posit<0) 
  445.         posit=0;
  446.     if (posit<=lastbyte) 
  447.         position=posit;
  448.     else 
  449.         position=lastbyte;
  450.     return(TRUE);
  451. }
  452.  
  453. static trace(a)
  454. char a;
  455. {
  456.     move(1,70);
  457.     addch(a);
  458.     refresh();
  459. }
  460.  
  461. static pos_print()
  462. {
  463.     char *ptr;
  464.  
  465.     ptr=pos+7;
  466.     *ptr--=hexchars[(position & 0xf)];
  467.     *ptr--=hexchars[((position>>4) & 0xf)];
  468.     *ptr--=hexchars[((position>>8) & 0xf)];
  469.     *ptr--=hexchars[((position>>12) & 0xf)];
  470.     *ptr--=hexchars[((position>>16) & 0xf)];
  471.     *ptr--=hexchars[((position>>20) & 0xf)];
  472.     *ptr--=hexchars[((position>>24) & 0xf)];
  473.     *ptr--=hexchars[((position>>28) & 0xf)];
  474.     *(ptr+8)=0;
  475.     mvaddstr(Y_STATUS,X_POSITION,pos);
  476. }
  477.  
  478. static editbuffer()
  479. {
  480.     /* Display edit headings    */
  481.     mvaddstr(Y_MENU1, X_MENU1,head5);
  482.     mvaddstr(Y_MENU2, X_MENU2,head6);
  483.     mvaddstr(Y_VERB, X_VERB,"Edit");
  484.     hex_ed();
  485.     mode = READING;
  486.         toplev_headings();
  487. }
  488.  
  489. /* read_headings: Display read headings */
  490. static toplev_headings()
  491. {
  492.     if (readonly)
  493.     {
  494.         mvaddstr(Y_MENU1, X_MENU1,r_head2);
  495.         mvaddstr(Y_MENU2, X_MENU2,r_head3);
  496.     }
  497.     else
  498.     {
  499.         mvaddstr(Y_MENU1, X_MENU1,head2);
  500.         mvaddstr(Y_MENU2, X_MENU2,head3);
  501.     }
  502.     mvaddstr(Y_VERB, X_VERB,"View");
  503.     move(Y_PROMPT, X_INPUT);
  504.     refresh();
  505. }
  506.  
  507. static char_ed()  /* Entered from hex_ed() when 'TAB' read. */
  508. {
  509.     char *ptr;
  510.     char *hptr;
  511.     char c1,c2;
  512.     int xx;
  513.     int num_read;
  514.  
  515.     /* get byte by mapping on to physical scale from screen scale         */
  516.     ptr=page+(y-7)*80+x;
  517.     move(y,x);
  518.     refresh();
  519.     do
  520.     {
  521.         ch=getch();
  522.         if ((ch)>=0x20 && (ch)<0x7f) 
  523.         {
  524.             addch(ch);
  525.             refresh();
  526.             *ptr = ch;
  527.             c1 = ch & 0xf;
  528.             c2 = (ch >> 4) & 0xf;
  529.             xx = (x - 52) * 3;
  530.             hptr = (ptr - x) + xx;
  531.             *hptr++ = hexchars[c2];
  532.             *hptr   = hexchars[c1];
  533.             move(y,xx);
  534.             addch(*--hptr);
  535.             addch(*++hptr);
  536.             refresh();
  537.             if (x == 67) 
  538.                 if (y < 22) 
  539.                 {
  540.                     ptr +=65;
  541.                     x = 52;
  542.                     y++;
  543.                 }
  544.                 else     
  545.                 {
  546.                     ptr = page + 52;
  547.                     x = 52;
  548.                     y = 7;
  549.                 }
  550.             else     
  551.             {
  552.                 ptr++;
  553.                 x++;
  554.             }
  555.         }
  556.         else if (ch==KEY_RIGHT)
  557.             if (x==67) 
  558.             {
  559.                 if (y<22) 
  560.                 {
  561.                     ptr+=65;
  562.                     x=52;
  563.                     y++;
  564.                 }
  565.                 else     
  566.                 {
  567.                     ptr=page+52;
  568.                     x=52;
  569.                     y=7;
  570.                 }
  571.             }
  572.             else     
  573.             {
  574.                 ptr++;
  575.                 x++;
  576.             }
  577.         else if (ch == KEY_LEFT)
  578.             if (x == 52) 
  579.             {
  580.                 if (y > 7) 
  581.                 {
  582.                     ptr -= 65;
  583.                     x = 67;
  584.                     y--;
  585.                 }
  586.                 else    
  587.                 {
  588.                     ptr += 1215;
  589.                     x = 67;
  590.                     y = 22;
  591.                 }
  592.             }
  593.             else    
  594.             {
  595.                 ptr--;
  596.                 x--;
  597.             }
  598.         else if (ch == KEY_UP) 
  599.             if (y > 7)    
  600.             {
  601.                 ptr -=80;
  602.                 y--;
  603.             }
  604.             else    
  605.             {
  606.                 ptr +=1200;
  607.                 y = 22;
  608.             }
  609.         else if (ch == KEY_DOWN) 
  610.             if (y < 22) 
  611.             {
  612.                 ptr +=80;
  613.                 y++;
  614.             }
  615.             else    
  616.             {
  617.                 ptr -=1200;
  618.                 y = 7;
  619.             }
  620.         else if (ch == KEY_ESC) 
  621.         {
  622.             lseek(input,position,0);
  623.             display();
  624.         }
  625.         else if ((ch == ENTER) || (ch == KEY_TAB))
  626.             /* do nothing */ ;
  627.         else 
  628.             beep();
  629.         move(y,x);
  630.         refresh();
  631.     }
  632.     while ((ch!=ENTER) && 
  633.                (ch!=KEY_TAB) && 
  634.                (ch!=KEY_ESC));
  635.     if (ch==ENTER) 
  636.     {
  637.         hex_to_buf();
  638.         lseek(input,position,0);
  639.         write(input,buf,bytes_read);
  640.     }
  641.     mode=READING;
  642. }
  643.  
  644. static hex_ed()
  645. {
  646.     char *ptr;
  647.     int num_read;
  648.  
  649.     ptr=page;
  650.     x=X_HEX;
  651.     y=Y_HEX;
  652.     move(y,x);
  653.     refresh();
  654.     do
  655.     {
  656.         ch=getch();
  657.         if (isxdigit(ch)) 
  658.         {
  659.             addch(toupper(ch));
  660.             refresh();
  661.             *ptr = ch;
  662.             {
  663.                 char *cptr,c1,c2;
  664.                 int xx;
  665.  
  666.                 if ((x%3) == 1)
  667.                     cptr = ptr - 1;
  668.                 else
  669.                     cptr = ptr;
  670.                 c1 = *cptr++;
  671.                 c2 = *cptr;
  672.                 if (c1 > '9')
  673.                     c1 = (c1 + 9) & 0xf;
  674.                 else
  675.                     c1 = c1 & 0xf;
  676.                 if (c2 > '9')
  677.                     c2 = (c2 + 9) & 0xf;
  678.                 else
  679.                     c2 = c2 & 0xf;
  680.                 c1 = (c1 << 4) + c2;
  681.                 xx = (x/3) + 52;
  682.                 move(y,xx);
  683.                 refresh();
  684.                 if ((c1>=0x20) && (c1<0x7f))
  685.                     addch(c1);
  686.                 else
  687.                     addch('.');
  688.                 refresh();
  689.             }
  690.             ptr++;
  691.             x++;
  692.             if (((x+1)%3)==0) 
  693.             {
  694.                 if (x==47) 
  695.                 {
  696.                     if (y<22) 
  697.                     {
  698.                         ptr+=33;
  699.                         x=0;
  700.                         y++;
  701.                     }
  702.                     else 
  703.                     {
  704.                         ptr=page;
  705.                         x=0;
  706.                         y=7;
  707.                     }
  708.                 }
  709.                 else    
  710.                 {
  711.                     ptr++;
  712.                     x++;
  713.                 }
  714.             }
  715.         }
  716.         else if (ch==KEY_RIGHT) 
  717.         {
  718.             ptr++;
  719.             x++;
  720.             if (((x+1)%3)==0) 
  721.                 if (x==47) 
  722.                     if (y<22) 
  723.                     {
  724.                         ptr+=33;
  725.                         x=0;
  726.                         y++;
  727.                     }
  728.                     else 
  729.                     {
  730.                         ptr=page;
  731.                         x=0;
  732.                         y=7;
  733.                     }
  734.                 else 
  735.                 {
  736.                     ptr++;
  737.                     x++;
  738.                 }
  739.         }
  740.         else if (ch==KEY_LEFT) 
  741.             if (x==0) 
  742.             {
  743.                 if (y>7) 
  744.                 {
  745.                     ptr -= 34;
  746.                     x = 46;
  747.                     y--;
  748.                 }
  749.                 else    
  750.                 {
  751.                     ptr += 1246;
  752.                     x = 46;
  753.                     y = 22;
  754.                 }
  755.             }
  756.             else    
  757.             {
  758.                 ptr--;
  759.                 x--;
  760.                 if (((x+1)%3)==0) 
  761.                 {
  762.                     ptr--;
  763.                     x--;
  764.                 }
  765.             }
  766.         else if (ch == KEY_UP) 
  767.             if (y > 7) 
  768.             {
  769.                 ptr -= 80;
  770.                 y--;
  771.             }
  772.             else     
  773.             {
  774.                 ptr += 1200;
  775.                 y = 22;
  776.             }
  777.         else if (ch == KEY_DOWN) 
  778.             if (y < 22) 
  779.             {
  780.                 ptr += 80;
  781.                 y++;
  782.             }
  783.             else 
  784.             {
  785.                 ptr -= 1200;
  786.                 y = 7;
  787.             }
  788.         else if (ch == KEY_ESC) 
  789.         {
  790.             lseek(input,position,0);
  791.             display();
  792.         }
  793.         else if (ch==ENTER);
  794.         else if (ch==KEY_TAB) 
  795.         { 
  796.             x = (x/3) + 52;
  797.             char_ed();
  798.             x = (x-52) * 3;
  799.             ptr = page + (y-7)*80 + x;
  800.         }
  801.         else 
  802.             beep();
  803.         move(y,x);
  804.         refresh();
  805.     }
  806.     while (ch!=ENTER && ch!=KEY_ESC);
  807.     if (ch==ENTER) 
  808.     {
  809.         hex_to_buf();
  810.         lseek(input,position,0);
  811.         write(input,buf,bytes_read);
  812.     }
  813. }
  814.  
  815. static hex_to_buf()
  816. {
  817.     char c1,c2;
  818.     int i;
  819.     int j;
  820.  
  821.     hptr = page;
  822.     bptr = buf;
  823.     for (i=0;i<16;i++) 
  824.     {
  825.         for (j=0;j<16;j++) 
  826.         {
  827.             c1 = *hptr++;
  828.             if (c1 > '9')
  829.                 c1 = (c1 + 9) & 0xf;
  830.             else
  831.                 c1 = c1 & 0xf;
  832.             c2 = *hptr++;
  833.             if (c2 > '9')
  834.                 c2 = (c2 + 9) & 0xf;
  835.             else
  836.                 c2 = c2 & 0xf;
  837.             *bptr++ = (c1 << 4) + c2;
  838.             hptr++;
  839.         }
  840.         hptr += 32;
  841.     }
  842. }
  843.  
  844.  
  845. static int get_string()
  846. {   
  847.     mvaddstr(Y_MENU1, X_MENU1,head7);
  848.     mvaddstr(Y_MENU2, X_MENU2,head8);
  849.     mvaddstr(Y_VERB, X_VERB,"Find");
  850.     attron(A_BOLD);
  851.     mvaddstr(6,0,"search criteria: ");
  852.     attroff(A_BOLD);
  853.     if ((bool_hexfind && !hex_find) || (!bool_hexfind && hex_find))
  854.     {
  855.         if (hex_find)
  856.             bool_hexfind=TRUE;
  857.         else if (!hex_find)
  858.             bool_hexfind=FALSE;
  859.         find_length=0;
  860.         disp_buff[0]=0;
  861.     }
  862.     if (hex_find)
  863.     {
  864.         buftoh(disp_buff,find_buff,find_length);
  865.         disp_length=find_length*2;
  866.     }
  867.     else
  868.         buftobuf(disp_buff,find_buff,disp_length=find_length);
  869.     if ((disp_length=get_str(stdscr,6,17,disp_buff,'.',
  870.          hex_find?DBUFF_SIZE:FBUFF_SIZE))==-1)
  871.     {
  872.         put_prompt();
  873.         return(FALSE);
  874.     }
  875.     else if (disp_length==0 && hex_find)
  876.         disp_length=find_length*2;
  877.     else if (disp_length==0 && !hex_find)
  878.         disp_length=find_length;
  879.     set_string();
  880.     return(TRUE);
  881. }
  882.  
  883. /* set_string: set up the string for return */
  884. static set_string()
  885. {
  886.     if (hex_find)
  887.     {
  888.         htobuf(find_buff,disp_buff,disp_length);
  889.         find_length=disp_length/2;
  890.     }
  891.     else 
  892.         buftobuf(find_buff,disp_buff,find_length=disp_length);
  893. }
  894.  
  895. /* buftoh: Converts input buffer to hexadecimal display in output string.
  896.  *         String length is used since zero is legitimate.
  897.  */
  898. static buftoh(out_string, in_string, in_size)
  899. char *in_string, *out_string;
  900. int in_size;
  901. {    
  902.     register int i;
  903.  
  904.     for (i=0; i < in_size; i++)
  905.     {
  906.         char ch = *in_string++;
  907.         *out_string++ = hexchars[(ch >> 4) & 0xf]; /* [ch/16]; */
  908.         *out_string++ = hexchars[ ch & 0xf]; /* [ch%16]; */
  909.     }
  910. }
  911.  
  912. /* htobuf: converts hexadecimal display to binary. String length is used
  913.  *         and only hexadecimal pairs are handled.
  914.  */
  915. static htobuf(out_string, in_string, in_size)
  916. char *in_string, *out_string;
  917. int in_size;
  918. {   
  919.     char i;
  920.     int h_value, c_value;
  921.     int byte_val;
  922.  
  923.     if (in_size%2 != 0) 
  924.     {
  925.         put_prompt();
  926.         addstr(error1);
  927.         beep();
  928.         refresh();
  929.         return;
  930.     }
  931.     for (i=0; i < in_size; i++)
  932.     {   
  933.         if ((h_value = *in_string++) >= '0' && h_value <= '9')
  934.                 c_value = h_value -'0';
  935.         else (c_value = 10 + (h_value & 0xf) - ('a' & 0xf));    
  936.         if (!(i%2))
  937.             byte_val = c_value * 16;
  938.         else 
  939.             *out_string++ = byte_val + c_value;
  940.     }
  941. }
  942.  
  943. /* buftobuf: Copy buffer to buffer. Not quite strncopy since zero is valid
  944.  *           and not a terminator.
  945.  */
  946. static buftobuf(out_string,in_string,in_size)
  947. char *in_string,*out_string;
  948. int in_size;
  949. {   
  950.     register int i;
  951.  
  952.     for (i=0; i<in_size; i++)
  953.         (*(out_string++))=(*(in_string++));
  954. }
  955.  
  956. /* find_string: Locates the string which has been specified by the user.
  957.  *        The search is carried out cyclically locating the string
  958.  *        specified at the beginning of the buffer. If the string is
  959.  *        not found we tell the user with a friendly message.
  960.  */
  961. int find_string()
  962. {   
  963.     long start_pos=position; /* hold start position to stop cyclic search */
  964.     int inc_length;
  965.     /* the number of start points for search in one buffer full */
  966.     int num_read; /* number read in this read */
  967.     int found_it=0;
  968.  
  969.     position ++;  /* make sure we move ahead */
  970.     inc_length=BUFSIZE-find_length;
  971.     /* search to the end of the file */
  972.     while (filedata.st_size>=position+find_length && found_it!=1)
  973.     {   
  974.         lseek(input,position,0);
  975.         num_read=read(input,buf,BUFSIZE);
  976.         if (search(buf,&position,num_read-find_length)) 
  977.             found_it=1;
  978.     } 
  979.     /* if still not found then search from beginning              */
  980.     if (found_it!=1)
  981.     {
  982.         position=0;
  983.         while (position<=start_pos && found_it!=1)
  984.         {   
  985.             lseek(input,position,0);
  986.             num_read=read(input,buf,BUFSIZE);
  987.             if (search(buf,&position,position+inc_length<start_pos?
  988.                      (int)inc_length:(int)(start_pos-position)))
  989.                 found_it=1;
  990.         }
  991.     }
  992.     if (found_it!=1)
  993.     {
  994.         put_prompt();
  995.         addstr(msg1);
  996.         beep();
  997.         refresh();
  998.         position = start_pos;
  999.         lseek(input,position,0);
  1000.         return;
  1001.     }
  1002.     lseek(input, position, 0);
  1003.     display();
  1004. }
  1005.  
  1006. /* search: Search for the field described by find_buff and find_length in 
  1007.  *         the parameter buf incrementing start as far as size.
  1008.  *         Returning true if the string is found.
  1009.  */
  1010. int search(buf,start,size)
  1011. char *buf;
  1012. long *start;
  1013. int size;
  1014. {   
  1015.     int i, j;
  1016.  
  1017.     i = 0;
  1018.     j = -1;
  1019.     while (i != find_length && j++ < size) /* loop through buffer */
  1020.     {   
  1021.         for (i=0; i<find_length && *(find_buff+i)==*(buf+i); i++)
  1022.         /* loop through string (no body) */ ;
  1023.         buf++;
  1024.         }
  1025.     *start+=j;
  1026.     return (i==find_length);
  1027. }
  1028.  
  1029. /* initialise term..                                  */
  1030. init_term()
  1031. {
  1032.     initscr();        /* init curses terminfo                      */
  1033.     keypad(stdscr,TRUE);    /* allow keypad use                      */
  1034.     noecho();        /* set terminal to noecho                     */
  1035.     cbreak();        /* raw input                           */
  1036. }
  1037.  
  1038. /* reset term to the way it was                                  */
  1039. reset_term()
  1040. {
  1041.     nocbreak();
  1042.     echo();
  1043.     endwin();
  1044. }
  1045.  
  1046. /* get string routine                                  */
  1047. int get_str(wnd,row,col,str,filler,str_size)
  1048. WINDOW *wnd;
  1049. int row,col,str_size;
  1050. char filler;
  1051. char *str;
  1052. {
  1053.     char out_buff[40];
  1054.     int ccol=0,c,erase_flg=0;
  1055.     register int i;
  1056.     int leave=FALSE;
  1057.     int status=0;
  1058.  
  1059.     for (i=0; i<str_size; i++)    /* paste filler to field          */
  1060.         mvwaddch(wnd,row,col+i,filler);
  1061.     /* print contents of str                          */
  1062.     for (i=0; i<disp_length; i++)
  1063.         mvwaddch(wnd,row,col+i,str[i]);
  1064.     wmove(wnd,row,col);            /* move to field start          */
  1065.     wrefresh(wnd);                /* refresh whats been done    */
  1066.     while (!leave)
  1067.     {
  1068.         c=wgetch(wnd);
  1069.         switch(c)
  1070.         {
  1071.             case '\n':
  1072.             case '\r':
  1073.                 leave=TRUE;
  1074.                 break;
  1075.             case KEY_HOME:
  1076.                 ccol=0;
  1077.                 wmove(wnd,row,col+ccol);
  1078.                 refresh();
  1079.                 break;
  1080.             case CTRL('h'):
  1081.                 if (ccol>0)
  1082.                 {
  1083.                     if (--ccol<0)
  1084.                         ccol=0;
  1085.                           mvwaddch(wnd,row,col+ccol,filler);
  1086.                     wmove(wnd,row,col+ccol);
  1087.                     *(str+ccol)=' ';
  1088.                     wrefresh(wnd);
  1089.                 }
  1090.                 else
  1091.                     beep();
  1092.                 break;
  1093.             case KEY_ESC:            /* if escape pressed */
  1094.                 status=(char)-1;
  1095.                 leave=TRUE;
  1096.                 break;
  1097.             case KEY_LEFT:
  1098.                 erase_flg=1;
  1099.                 if (ccol>0)
  1100.                 {
  1101.                     if (--ccol<0)
  1102.                         ccol=0;
  1103.                               wmove(wnd,row,col+ccol);
  1104.                     wrefresh(wnd);
  1105.                 }
  1106.                 else
  1107.                     beep();
  1108.                 break;
  1109.             case KEY_RIGHT:
  1110.                 if (ccol<str_size-1)
  1111.                 {
  1112.                     if (++ccol>str_size)
  1113.                         ccol=str_size;
  1114.                         wmove(wnd,row,col+ccol);
  1115.                     wrefresh(wnd);
  1116.                 }
  1117.                 else
  1118.                     beep();
  1119.                 break;    
  1120.             default:            /* other chars         */
  1121.                 if ((((hex_find || mode==GOTO) && 
  1122.                         isxdigit(c)) || 
  1123.                     ((!hex_find && mode!=GOTO) && 
  1124.                     (c>=0x20 && c<0x7f))) &&
  1125.                     ccol<str_size)
  1126.                 {
  1127.                     if (erase_flg==0)
  1128.                         for (i=0; i<str_size; i++)
  1129.                         {
  1130.                             mvwaddch(wnd,row,col+i,
  1131.                                 filler);
  1132.                             str[i]=' ';
  1133.                         }
  1134.                     mvwaddch(wnd,row,col+ccol,c);
  1135.                     wrefresh(wnd);
  1136.                     *(str+ccol)=c;
  1137.                     if (++ccol>str_size)
  1138.                         ccol=str_size;
  1139.                 }
  1140.                 else
  1141.                     beep();
  1142.                 break;
  1143.         }
  1144.         erase_flg=1;
  1145.     }
  1146.     if (status==0)
  1147.         status=ccol;
  1148.     return(status);
  1149. }
  1150.  
  1151. ctrlc_ast(sig)
  1152. int sig;
  1153. {
  1154.     if (sig==SIGINT)
  1155.         closedown();
  1156.     else
  1157.         signal(SIGINT,ctrlc_ast);
  1158. }
  1159.  
  1160. put_prompt()
  1161. {
  1162.     move(6,0);
  1163.     clrtoeol();
  1164.     attron(A_BOLD);
  1165.     mvaddstr(Y_PROMPT, X_PROMPT,"command> ");
  1166.     attroff(A_BOLD);
  1167. }
  1168.  
  1169. edit_headings()
  1170. {
  1171.     mvaddstr(Y_MENU1, X_MENU1,edit1);
  1172.     mvaddstr(Y_MENU2, X_MENU2,edit2);
  1173.     mvaddstr(Y_VERB, X_VERB,"Goto");
  1174. }
  1175. SHAR_EOF
  1176. fi # end of overwriting check
  1177. #    End of shell archive
  1178. exit 0
  1179.  
  1180. ------- End of Forwarded Message
  1181.  
  1182.  
  1183.  
  1184. ----- End Included Message -----
  1185.  
  1186.  
  1187. -- 
  1188.  
  1189. Ken Keirnan - Pacific Bell - kjkeirn@srv.PacBell.COM
  1190.   San Ramon, California
  1191.